package com.walter.redis.tools;

import io.micrometer.common.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RedissonClient;

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;


/**
 *  布隆过滤器服务
 * @author Walter
 * @date 2025/1/11 下午3:13
 */
@Slf4j
public class BloomFilterService {
    /**
     * 读写锁
     */
    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    /**
     * 布隆过滤器在 Redis 中的名称 (作为 key 的一部分)
     */
    private final String BLOOM_FILTER_NAME;
    /**
     * Redisson 客户端
     */
    private final RedissonClient redissonClient;

    /**
     *  构造函数
     * @param redissonClient Redisson 客户端
     * @param bloomFilterName 布隆过滤器在 Redis 中的名称
     * @param expectedInsertions 预期插入数量
     * @param falsePositiveProbability 误判率(例如 0.01 表示 1% 的误判率)
     */
    public BloomFilterService(RedissonClient redissonClient,String bloomFilterName, int expectedInsertions, double falsePositiveProbability) {
        this.redissonClient = redissonClient;
        this.BLOOM_FILTER_NAME = bloomFilterName;
        redissonClient.getBloomFilter(BLOOM_FILTER_NAME).tryInit(expectedInsertions, falsePositiveProbability);
    }

    /**
     * 添加到布隆过滤器
     *
     * @param element   要添加的元素
     * @return  添加成功 true；添加失败 false
     */
    public boolean add(String element) {
        // 检查是否已经初始化
        assertInjected();
        if (StringUtils.isBlank(element)) {
            return false;
        }
        try {
            readWriteLock.writeLock().lock();
            return redissonClient.getBloomFilter(BLOOM_FILTER_NAME).add(element);
        } finally {
            readWriteLock.writeLock().unlock();
        }
    }

    /**
     * 检查元素是否可能存在于布隆过滤器中
     *
     * @param element 要检查的元素
     * @return true 如果元素可能存在；false 如果元素一定不存在
     */
    public boolean exist(String element) {
        // 检查是否已经初始化
        assertInjected();
        if (StringUtils.isBlank(element)) {
            return false;
        }
        try {
            readWriteLock.readLock().lock();
            return redissonClient.getBloomFilter(BLOOM_FILTER_NAME).contains(element);
        } finally {
            readWriteLock.readLock().unlock();
        }
    }

    /**
     * 清除布隆过滤器
     */
    public void clear() {
        // 检查是否已经初始化
        assertInjected();
        redissonClient.getBloomFilter(BLOOM_FILTER_NAME).delete();
    }

    /**
     * 检查布隆过滤器.
     */
    private void assertInjected() {
        if (null == redissonClient) {
            throw new IllegalStateException("布隆过滤器未初始化");
        }
    }
}